/******************************************
Cola_implementacion_lista.java
Universidad del Valle de Guatemala
Algoritmos y Estructura de Datos
Autor:
    Martín Guzmán
Fecha: 15 de julio de 2009
Descripción: Implementación de una cola
 * utilizando listas circulares
*******************************************/
import java.util.ArrayList;
import java.lang.reflect.Array;
import java.lang.AssertionError;

public class Cola_implementacion_lista<G> extends Cola<G> {
    Nodo<G> principio_lista;
    Nodo<G> ultimo_lista;

    //método constructor
    public Cola_implementacion_lista(){
        super();
        disponibles=10;
        principio_lista=null;
    }


    //regresa la cantidad de espacios disponibles en la pila
    public int getDisponibles() {
        return this.disponibles;
    }

   
    //método para sacar el último elemento de la pila
    public G pop() {
        assert this.disponibles!=10:"No se puede hacer un pop() sin antes haber metido nada...";
        if(this.empty()==true){ //revisa si está vacío
            System.out.println("*** Lo sentimos, no puede sacar el último elemento de la pila debido a que está vacía ****");
            return null;
        }

        Nodo<G> temporal = this.principio_lista.getSiguiente_nodo();
        //System.out.println("EL DATO QUE SE SACÖ FUE: "+temporal.getValor().toString());//TODO quitar esto...
        G return_value = temporal.getValor();

        this.principio_lista.setSiguiente_nodo(temporal.getSiguiente_nodo());

        this.disponibles++;
        return return_value;
    }
    
    //me retorna el índice en el que se encuentra el elemento dado
    //en caso de no encontrarse, retorna -1
    public int posicion_de(G Elemento_G){
        Nodo<G> temporal = this.principio_lista.getSiguiente_nodo();
        for(int i=1;i<=(this.max-this.disponibles);i++){
            if(temporal.getValor().toString().compareTo(Elemento_G.toString())==0)
            {
                return i-1;
            }
            temporal=temporal.getSiguiente_nodo();
        }
        return -1;
    }

    //método para que ingrese un nuevo elemento a la pila
    public void push(G Elemento_G) {
        assert this.disponibles!=0:"No se puede hacer un push() cuando ya hay 10 elementos metidos en la pila";
        if(this.disponibles!=0){ //el parqueo está lleno si disponibles=0
            if(this.empty()==true){ //el primer push
                principio_lista = new Nodo<G>(null,new Nodo<G>(Elemento_G,null,principio_lista),this.ultimo_lista);//como es lista circular, el primero hacer referencia al último
                this.ultimo_lista=this.principio_lista.getSiguiente_nodo();
            }
            else
            {
                this.ultimo_lista.setSiguiente_nodo(new Nodo<G>(Elemento_G,null,ultimo_lista));
                this.ultimo_lista = this.ultimo_lista.getSiguiente_nodo();
            }
            disponibles-=1; //entró un elemento, por lo tanto hay uno menos disponible
        }
        else
        {
            //esto no va a dar porque cuando se llama al método se controla esto...
            System.out.println("******** Lo sentimos, ya no hay espacios disponibles *****");
        }
    }

    public String toString(){
        String temporal="|";
        try{
            Nodo<G> temporal2 = this.principio_lista.getSiguiente_nodo();
            while (temporal2!=this.ultimo_lista.getSiguiente_nodo()){
                temporal=temporal+" "+temporal2.getValor().toString()+" |";
                temporal2=temporal2.getSiguiente_nodo();
            }
            for (int i=0;i<this.disponibles;i++){
                temporal+="--|";
            }
        }catch(Exception ex)
        {
            return "|--|--|--|--|--|--|--|--|--|--|";
        }
         
        return temporal;
    }

    public G primera_Posicion() {
        G temporal = this.principio_lista.getSiguiente_nodo().getValor();
        return temporal;
    }

}